#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import logging
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import TimeoutException, NoSuchElementException

from tests.page_objects.base_page import BasePage

class ProductPage(BasePage):
    """宠物用品页面对象"""
    
    # 导航菜单定位器
    PET_SUPPLIES_MENU = (By.XPATH, "//span[text()='宠物用品']")
    PET_SUPPLIES_MANAGEMENT = (By.XPATH, "//li[contains(@class, 'el-menu-item')][.//text()='宠物用品管理']")
    
    # 搜索表单定位器
    PRODUCT_NAME_INPUT = (By.XPATH, "//label[text()='商品名称']/following-sibling::div//input")
    CATEGORY_SELECT = (By.XPATH, "//label[text()='商品分类']/following-sibling::div//input")
    STATUS_SELECT = (By.XPATH, "//label[text()='商品状态']/following-sibling::div//input")
    SEARCH_BUTTON = (By.XPATH, "//form[contains(@class, 'el-form')]//button[contains(@class, 'el-button--primary')][.//span[text()='搜索']]")
    RESET_BUTTON = (By.XPATH, "//form[contains(@class, 'el-form')]//button[.//span[text()='重置']]")
    
    # 表格定位器
    PRODUCT_TABLE = (By.XPATH, "//table[contains(@class, 'el-table')]")
    TABLE_ROWS = (By.XPATH, "//table[contains(@class, 'el-table')]//tbody/tr")
    TABLE_LOADING = (By.XPATH, "//div[contains(@class, 'el-loading-mask')]")
    
    # 表格操作按钮定位器
    FIRST_ROW_EDIT_BUTTON = (By.XPATH, "//table[contains(@class, 'el-table')]//tbody/tr[1]//button[contains(@class, 'el-button--primary')][.//span[text()='编辑']]")
    
    # 分页定位器
    PAGINATION = (By.XPATH, "//div[contains(@class, 'pagination-container')]//ul[contains(@class, 'el-pagination')]")
    
    # 添加商品相关定位器
    ADD_PRODUCT_BUTTON = (By.XPATH, "//button[contains(@class, 'el-button--primary')][.//span[text()='添加商品']]")
    
    # 添加/编辑商品对话框定位器
    DIALOG = (By.XPATH, "//div[contains(@class, 'el-dialog')]")
    DIALOG_TITLE = (By.XPATH, "//div[contains(@class, 'el-dialog__title')]")
    DIALOG_PRODUCT_NAME_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='商品名称']/following-sibling::div//input")
    DIALOG_CATEGORY_SELECT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='商品分类']/following-sibling::div//input")
    DIALOG_PRICE_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='商品价格']/following-sibling::div//input")
    DIALOG_STOCK_INPUT = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='商品库存']/following-sibling::div//input")
    DIALOG_STATUS_RADIO_UP = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[contains(@class, 'el-radio')][.//span[text()='上架']]")
    DIALOG_STATUS_RADIO_DOWN = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[contains(@class, 'el-radio')][.//span[text()='下架']]")
    DIALOG_DESCRIPTION_TEXTAREA = (By.XPATH, "//div[contains(@class, 'el-dialog')]//label[text()='商品描述']/following-sibling::div//textarea")
    DIALOG_CONFIRM_BUTTON = (By.XPATH, "//div[contains(@class, 'dialog-footer')]//button[contains(@class, 'el-button--primary')][.//span[text()='确认']]")
    DIALOG_CANCEL_BUTTON = (By.XPATH, "//div[contains(@class, 'dialog-footer')]//button[.//span[text()='取消']]")
    
    # 下拉选项定位器
    DROPDOWN_ITEM = (By.XPATH, "//div[contains(@class, 'el-select-dropdown') and not(contains(@style, 'display: none'))]//div[contains(@class, 'el-select-dropdown__item')]")
    
    def __init__(self, driver):
        super().__init__(driver)
        self.actions = ActionChains(driver)
    
    def navigate_to_product_page(self):
        """
        导航到宠物用品管理页面
        """
        logging.info("导航到宠物用品管理页面")
        
        try:
            # 等待宠物用品菜单可见并点击
            try:
                pet_supplies_menu = self.wait.until(EC.element_to_be_clickable(self.PET_SUPPLIES_MENU))
                pet_supplies_menu.click()
                logging.info("已点击宠物用品菜单")
            except Exception as e:
                logging.warning(f"点击宠物用品菜单失败: {e}")
                # 使用更通用的XPath
                try:
                    pet_supplies_menu = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//span[contains(text(), '宠物用品')]")))
                    pet_supplies_menu.click()
                    logging.info("已使用通用XPath点击宠物用品菜单")
                except Exception as e2:
                    logging.warning(f"使用通用XPath点击宠物用品菜单失败: {e2}")
                    # 使用JavaScript点击
                    self.driver.execute_script("""
                    var menuItems = document.querySelectorAll('span');
                    for (var i = 0; i < menuItems.length; i++) {
                        if (menuItems[i].textContent.includes('宠物用品')) {
                            menuItems[i].click();
                            console.log('已通过JavaScript点击宠物用品菜单');
                            break;
                        }
                    }
                    """)
            
            # 等待子菜单展开
            time.sleep(2)
            
            # 点击宠物用品管理子菜单
            try:
                pet_supplies_management = self.wait.until(EC.element_to_be_clickable(self.PET_SUPPLIES_MANAGEMENT))
                pet_supplies_management.click()
                logging.info("已点击宠物用品管理子菜单")
            except Exception as e:
                logging.warning(f"点击宠物用品管理子菜单失败: {e}")
                # 使用更通用的XPath
                try:
                    pet_supplies_management = self.wait.until(EC.element_to_be_clickable((By.XPATH, "//li[contains(@class, 'el-menu-item')][contains(., '宠物用品管理')]")))
                    pet_supplies_management.click()
                    logging.info("已使用通用XPath点击宠物用品管理子菜单")
                except Exception as e2:
                    logging.warning(f"使用通用XPath点击宠物用品管理子菜单失败: {e2}")
                    # 使用JavaScript点击
                    self.driver.execute_script("""
                    var subMenuItems = document.querySelectorAll('li.el-menu-item');
                    for (var i = 0; i < subMenuItems.length; i++) {
                        if (subMenuItems[i].textContent.includes('宠物用品管理')) {
                            subMenuItems[i].click();
                            console.log('已通过JavaScript点击宠物用品管理子菜单');
                            break;
                        }
                    }
                    """)
            
            # 等待页面加载
            time.sleep(5)  # 增加等待时间
            
            try:
                self.wait.until(EC.presence_of_element_located(self.PRODUCT_TABLE))
                logging.info("宠物用品管理页面已加载")
            except Exception as e:
                logging.warning(f"等待宠物用品管理页面加载失败: {e}")
            
            # 截图
            self.take_screenshot("product_page_loaded")
            
            return self
        except Exception as e:
            logging.error(f"导航到宠物用品管理页面失败: {e}")
            self.take_screenshot("navigate_to_product_page_failed")
            
            # 尝试使用JavaScript点击
            try:
                logging.info("尝试使用JavaScript导航到宠物用品管理页面")
                self.driver.execute_script("""
                // 尝试点击宠物用品菜单
                function clickPetSuppliesMenu() {
                    // 方法1：使用XPath
                    try {
                        var petSuppliesMenu = document.evaluate("//span[text()='宠物用品']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                        if (petSuppliesMenu) {
                            petSuppliesMenu.click();
                            console.log("已点击宠物用品菜单(XPath)");
                            return true;
                        }
                    } catch(e) {
                        console.error("XPath查找宠物用品菜单失败: " + e);
                    }
                    
                    // 方法2：遍历所有span元素
                    var spans = document.querySelectorAll('span');
                    for (var i = 0; i < spans.length; i++) {
                        if (spans[i].textContent.includes('宠物用品')) {
                            spans[i].click();
                            console.log("已点击宠物用品菜单(遍历)");
                            return true;
                        }
                    }
                    
                    // 方法3：查找带有宠物用品图标的菜单
                    var menuItems = document.querySelectorAll('.el-sub-menu__title');
                    for (var i = 0; i < menuItems.length; i++) {
                        if (menuItems[i].textContent.includes('宠物用品')) {
                            menuItems[i].click();
                            console.log("已点击宠物用品菜单(菜单项)");
                            return true;
                        }
                    }
                    
                    console.error("未找到宠物用品菜单");
                    return false;
                }
                
                // 尝试点击宠物用品管理子菜单
                function clickPetSuppliesManagementMenu() {
                    // 方法1：使用XPath
                    try {
                        var petSuppliesManagement = document.evaluate("//li[contains(@class, 'el-menu-item')][.//text()='宠物用品管理']", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
                        if (petSuppliesManagement) {
                            petSuppliesManagement.click();
                            console.log("已点击宠物用品管理子菜单(XPath)");
                            return true;
                        }
                    } catch(e) {
                        console.error("XPath查找宠物用品管理子菜单失败: " + e);
                    }
                    
                    // 方法2：遍历所有li元素
                    var items = document.querySelectorAll('li.el-menu-item');
                    for (var i = 0; i < items.length; i++) {
                        if (items[i].textContent.includes('宠物用品管理')) {
                            items[i].click();
                            console.log("已点击宠物用品管理子菜单(遍历)");
                            return true;
                        }
                    }
                    
                    console.error("未找到宠物用品管理子菜单");
                    return false;
                }
                
                // 执行点击操作
                var menuClicked = clickPetSuppliesMenu();
                
                // 等待子菜单展开
                setTimeout(function() {
                    var subMenuClicked = clickPetSuppliesManagementMenu();
                    if (!subMenuClicked) {
                        console.error("点击宠物用品管理子菜单失败");
                    }
                }, 1000);
                """)
                
                # 等待页面加载
                time.sleep(5)
                self.take_screenshot("product_page_loaded_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript导航到宠物用品管理页面也失败: {e2}")
                self.take_screenshot("navigate_to_product_page_js_failed")
                raise
    
    def search_product(self, name=None, category=None, status=None):
        """
        搜索商品
        
        Args:
            name: 商品名称，可选
            category: 商品分类，可选
            status: 商品状态，可选（上架/下架）
        """
        logging.info(f"搜索商品：名称={name}, 分类={category}, 状态={status}")
        
        try:
            # 等待搜索表单可见
            self.wait.until(EC.visibility_of_element_located(self.PRODUCT_NAME_INPUT))
            
            # 清空并填写商品名称
            if name is not None:
                name_input = self.driver.find_element(*self.PRODUCT_NAME_INPUT)
                name_input.clear()
                name_input.send_keys(name)
                logging.info(f"已输入商品名称: {name}")
            
            # 选择商品分类
            if category is not None:
                # 点击分类下拉框
                category_select = self.driver.find_element(*self.CATEGORY_SELECT)
                category_select.click()
                logging.info("已点击分类下拉框")
                time.sleep(1)  # 等待下拉菜单显示
                
                # 使用JavaScript选择分类
                self.driver.execute_script(f"""
                var options = document.querySelectorAll('.el-select-dropdown__item');
                console.log("找到选项数量: " + options.length);
                
                for (var i = 0; i < options.length; i++) {{
                    if (options[i].textContent.includes('{category}')) {{
                        options[i].click();
                        console.log('已选择分类: {category}');
                        break;
                    }}
                }}
                """)
                logging.info(f"已选择商品分类: {category}")
                time.sleep(1)  # 等待选择生效
            
            # 选择商品状态
            if status is not None:
                # 点击状态下拉框
                status_select = self.driver.find_element(*self.STATUS_SELECT)
                status_select.click()
                logging.info("已点击状态下拉框")
                time.sleep(1)  # 等待下拉菜单显示
                
                # 使用JavaScript选择状态
                self.driver.execute_script(f"""
                var options = document.querySelectorAll('.el-select-dropdown__item');
                console.log("找到选项数量: " + options.length);
                
                for (var i = 0; i < options.length; i++) {{
                    if (options[i].textContent.includes('{status}')) {{
                        options[i].click();
                        console.log('已选择状态: {status}');
                        break;
                    }}
                }}
                """)
                logging.info(f"已选择商品状态: {status}")
                time.sleep(1)  # 等待选择生效
            
            # 截图记录填写完表单的状态
            self.take_screenshot("form_filled")
            
            # 点击搜索按钮
            search_button = self.driver.find_element(*self.SEARCH_BUTTON)
            search_button.click()
            logging.info("已点击搜索按钮")
            
            # 等待加载完成
            time.sleep(3)  # 确保结果加载完成
            
            # 截图记录搜索结果
            self.take_screenshot("product_search_results")
            
            return self
        except Exception as e:
            logging.error(f"搜索商品失败: {e}")
            self.take_screenshot("search_product_failed")
            
            # 尝试使用JavaScript搜索
            try:
                logging.info("尝试使用JavaScript搜索商品")
                
                # 清空并填写商品名称
                if name is not None:
                    self.driver.execute_script(f"""
                    var nameInput = document.querySelector('input[placeholder="请输入商品名称"]');
                    if (nameInput) {{
                        nameInput.value = "{name}";
                        nameInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已输入商品名称: {name}");
                    }}
                    """)
                
                # 选择商品分类
                if category is not None:
                    self.driver.execute_script(f"""
                    // 点击分类下拉框
                    var categorySelect = document.querySelector('.el-form-item:nth-child(2) .el-select .el-input');
                    if (categorySelect) {{
                        categorySelect.click();
                        console.log("已点击分类下拉框");
                        
                        // 等待下拉菜单显示
                        setTimeout(function() {{
                            var options = document.querySelectorAll('.el-select-dropdown__item');
                            console.log("找到选项数量: " + options.length);
                            
                            for (var i = 0; i < options.length; i++) {{
                                if (options[i].textContent.includes('{category}')) {{
                                    options[i].click();
                                    console.log('已选择分类: {category}');
                                    break;
                                }}
                            }}
                        }}, 500);
                    }}
                    """)
                    time.sleep(1)
                
                # 选择商品状态
                if status is not None:
                    self.driver.execute_script(f"""
                    // 点击状态下拉框
                    var statusSelect = document.querySelector('.el-form-item:nth-child(3) .el-select .el-input');
                    if (statusSelect) {{
                        statusSelect.click();
                        console.log("已点击状态下拉框");
                        
                        // 等待下拉菜单显示
                        setTimeout(function() {{
                            var options = document.querySelectorAll('.el-select-dropdown__item');
                            console.log("找到选项数量: " + options.length);
                            
                            for (var i = 0; i < options.length; i++) {{
                                if (options[i].textContent.includes('{status}')) {{
                                    options[i].click();
                                    console.log('已选择状态: {status}');
                                    break;
                                }}
                            }}
                        }}, 500);
                    }}
                    """)
                    time.sleep(1)
                
                # 截图记录填写完表单的状态
                self.take_screenshot("form_filled_js")
                
                # 点击搜索按钮
                self.driver.execute_script("""
                var searchButton = document.querySelector('form.el-form button.el-button--primary');
                if (searchButton) {
                    searchButton.click();
                    console.log("已点击搜索按钮");
                } else {
                    console.error("未找到搜索按钮");
                }
                """)
                
                # 等待加载完成
                time.sleep(3)
                
                # 截图记录搜索结果
                self.take_screenshot("product_search_results_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript搜索商品也失败: {e2}")
                self.take_screenshot("search_product_js_failed")
                raise
    
    def reset_search(self):
        """
        重置搜索条件
        """
        logging.info("重置搜索条件")
        
        try:
            reset_button = self.driver.find_element(*self.RESET_BUTTON)
            reset_button.click()
            logging.info("已点击重置按钮")
            
            # 等待加载完成
            try:
                WebDriverWait(self.driver, 5).until(EC.invisibility_of_element_located(self.TABLE_LOADING))
            except TimeoutException:
                logging.warning("等待加载完成超时，继续执行")
            
            # 截图
            self.take_screenshot("reset_search_results")
            
            return self
        except Exception as e:
            logging.error(f"重置搜索条件失败: {e}")
            self.take_screenshot("reset_search_failed")
            raise
    
    def get_product_count(self):
        """
        获取商品列表中的商品数量
        
        Returns:
            int: 商品数量
        """
        try:
            rows = self.driver.find_elements(*self.TABLE_ROWS)
            count = len(rows)
            logging.info(f"商品列表中有 {count} 个商品")
            return count
        except Exception as e:
            logging.error(f"获取商品数量失败: {e}")
            return 0
    
    def is_product_in_results(self, name=None, category=None, status=None):
        """
        检查搜索结果中是否包含指定条件的商品
        
        Args:
            name: 商品名称，可选
            category: 商品分类，可选
            status: 商品状态，可选（上架/下架）
            
        Returns:
            bool: 是否找到匹配的商品
        """
        logging.info(f"检查搜索结果中是否包含商品：名称={name}, 分类={category}, 状态={status}")
        
        try:
            # 等待表格加载完成
            time.sleep(3)
            
            # 截图记录表格内容
            self.take_screenshot("product_table_content")
            
            # 使用JavaScript检查表格内容
            script = """
            // 获取表格行
            var rows = document.querySelectorAll('table tbody tr');
            console.log("表格行数: " + rows.length);
            
            // 检查表格是否为空
            if (rows.length === 0) {
                console.log("表格为空，没有搜索结果");
                return {
                    count: 0,
                    products: []
                };
            }
            
            // 收集所有产品信息
            var products = [];
            for (var i = 0; i < rows.length; i++) {
                var cells = rows[i].querySelectorAll('td');
                var productInfo = {
                    id: cells[0] ? cells[0].textContent.trim() : '',
                    name: '',
                    category: '',
                    status: ''
                };
                
                // 遍历所有单元格，查找相关信息
                for (var j = 0; j < cells.length; j++) {
                    var cellText = cells[j].textContent.trim();
                    
                    // 记录单元格内容
                    console.log(`行 ${i+1}, 单元格 ${j+1}: ${cellText}`);
                    
                    // 商品名称通常在第3列（索引2）
                    if (j === 2) {
                        productInfo.name = cellText;
                    }
                    
                    // 分类通常在第4列（索引3）
                    if (j === 3) {
                        productInfo.category = cellText;
                    }
                    
                    // 状态通常在第7列（索引6）
                    if (j === 6) {
                        productInfo.status = cellText;
                    }
                }
                
                console.log("产品信息: " + JSON.stringify(productInfo));
                products.push(productInfo);
            }
            
            return {
                count: rows.length,
                products: products
            };
            """
            
            result = self.driver.execute_script(script)
            product_count = result.get('count', 0)
            products = result.get('products', [])
            
            logging.info(f"找到 {product_count} 个商品")
            
            if product_count == 0:
                logging.info("表格为空，没有搜索结果")
                return False
            
            # 遍历所有商品，检查是否有匹配的
            for product in products:
                match = True
                
                if name is not None and name not in product.get('name', ''):
                    match = False
                    logging.debug(f"名称不匹配: {name} 不在 {product.get('name', '')}")
                
                if category is not None and category != product.get('category', ''):
                    match = False
                    logging.debug(f"分类不匹配: {category} != {product.get('category', '')}")
                
                if status is not None and status != product.get('status', ''):
                    match = False
                    logging.debug(f"状态不匹配: {status} != {product.get('status', '')}")
                
                if match:
                    logging.info(f"找到匹配的商品: {product}")
                    return True
            
            # 如果没有找到匹配的商品
            logging.info("未找到匹配的商品")
            return False
            
        except Exception as e:
            logging.error(f"检查商品是否在搜索结果中失败: {e}")
            self.take_screenshot("check_product_in_results_failed")
            return False
    
    def click_add_product_button(self):
        """
        点击添加商品按钮
        """
        logging.info("点击添加商品按钮")
        
        try:
            # 确保页面已加载
            time.sleep(2)
            
            # 点击添加商品按钮
            add_button = self.wait.until(EC.element_to_be_clickable(self.ADD_PRODUCT_BUTTON))
            add_button.click()
            logging.info("已点击添加商品按钮")
            
            # 等待对话框出现
            self.wait.until(EC.visibility_of_element_located(self.DIALOG))
            logging.info("添加商品对话框已打开")
            
            # 截图
            self.take_screenshot("add_product_dialog_opened")
            
            return self
        except Exception as e:
            logging.error(f"点击添加商品按钮失败: {e}")
            self.take_screenshot("click_add_product_button_failed")
            
            # 尝试使用JavaScript点击
            try:
                logging.info("尝试使用JavaScript点击添加商品按钮")
                self.driver.execute_script("""
                var buttons = document.querySelectorAll('button.el-button--primary');
                
                for (var i = 0; i < buttons.length; i++) {
                    if (buttons[i].textContent.includes('添加商品')) {
                        buttons[i].click();
                        console.log('已通过JavaScript点击添加商品按钮');
                        break;
                    }
                }
                """)
                
                # 等待对话框出现
                time.sleep(2)
                self.take_screenshot("add_product_dialog_opened_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript点击添加商品按钮也失败: {e2}")
                self.take_screenshot("click_add_product_button_js_failed")
                raise
    
    def fill_product_form(self, name, category, price, stock, status="上架", description=""):
        """
        填写商品表单
        
        Args:
            name: 商品名称
            category: 商品分类
            price: 商品价格
            stock: 商品库存
            status: 商品状态，默认为"上架"
            description: 商品描述，可选
        """
        logging.info(f"填写商品表单: 名称={name}, 分类={category}, 价格={price}, 库存={stock}, 状态={status}")
        
        try:
            # 确保对话框已显示
            self.wait.until(EC.visibility_of_element_located(self.DIALOG))
            
            # 输入商品名称
            name_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_PRODUCT_NAME_INPUT))
            name_input.clear()
            name_input.send_keys(name)
            logging.info(f"已输入商品名称: {name}")
            
            # 选择商品分类 - 改进选择分类的方法
            category_select = self.wait.until(EC.element_to_be_clickable(self.DIALOG_CATEGORY_SELECT))
            category_select.click()
            logging.info("已点击分类下拉框")
            time.sleep(1)  # 等待下拉菜单显示
            
            # 截图记录下拉菜单状态
            self.take_screenshot("category_dropdown_opened")
            
            # 定位并点击下拉菜单中的选项
            try:
                # 使用更精确的定位器找到可见的下拉菜单中的选项
                dropdown_items = self.wait.until(EC.presence_of_all_elements_located(self.DROPDOWN_ITEM))
                logging.info(f"找到 {len(dropdown_items)} 个下拉选项")
                
                # 遍历选项并查找匹配的分类
                category_found = False
                for item in dropdown_items:
                    if category in item.text:
                        logging.info(f"找到匹配的分类选项: {item.text}")
                        # 使用JavaScript点击，避免可能的元素遮挡问题
                        self.driver.execute_script("arguments[0].click();", item)
                        category_found = True
                        logging.info(f"已选择商品分类: {category}")
                        break
                
                if not category_found:
                    logging.warning(f"未找到匹配的分类: {category}")
                    # 尝试使用索引选择第一个选项
                    if dropdown_items:
                        self.driver.execute_script("arguments[0].click();", dropdown_items[0])
                        logging.info(f"已选择第一个可用分类: {dropdown_items[0].text}")
            except Exception as e:
                logging.error(f"选择分类失败: {e}")
                # 使用JavaScript尝试选择分类
                self.driver.execute_script(f"""
                var dropdowns = document.querySelectorAll('.el-select-dropdown:not([style*="display: none"])');
                if (dropdowns.length > 0) {{
                    var items = dropdowns[dropdowns.length-1].querySelectorAll('.el-select-dropdown__item');
                    console.log("找到 " + items.length + " 个下拉选项");
                    
                    var categoryFound = false;
                    for (var i = 0; i < items.length; i++) {{
                        if (items[i].textContent.includes('{category}')) {{
                            items[i].click();
                            console.log('已选择分类: ' + items[i].textContent);
                            categoryFound = true;
                            break;
                        }}
                    }}
                    
                    if (!categoryFound && items.length > 0) {{
                        items[0].click();
                        console.log('未找到匹配分类，已选择第一个选项: ' + items[0].textContent);
                    }}
                }}
                """)
            
            time.sleep(1)  # 等待选择生效
            self.take_screenshot("after_category_selection")
            
            # 输入商品价格
            price_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_PRICE_INPUT))
            # 对于数字输入框，先清除再设置值
            self.driver.execute_script(f"arguments[0].value = ''; arguments[0].dispatchEvent(new Event('input'));", price_input)
            price_input.send_keys(str(price))
            logging.info(f"已输入商品价格: {price}")
            
            # 输入商品库存
            stock_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_STOCK_INPUT))
            # 对于数字输入框，先清除再设置值
            self.driver.execute_script(f"arguments[0].value = ''; arguments[0].dispatchEvent(new Event('input'));", stock_input)
            stock_input.send_keys(str(stock))
            logging.info(f"已输入商品库存: {stock}")
            
            # 选择商品状态
            if status == "上架":
                status_radio = self.wait.until(EC.element_to_be_clickable(self.DIALOG_STATUS_RADIO_UP))
            else:
                status_radio = self.wait.until(EC.element_to_be_clickable(self.DIALOG_STATUS_RADIO_DOWN))
            status_radio.click()
            logging.info(f"已选择商品状态: {status}")
            
            # 输入商品描述
            if description:
                description_textarea = self.wait.until(EC.visibility_of_element_located(self.DIALOG_DESCRIPTION_TEXTAREA))
                description_textarea.clear()
                description_textarea.send_keys(description)
                logging.info(f"已输入商品描述: {description}")
            
            # 截图记录填写完表单的状态
            self.take_screenshot("product_form_filled")
            
            return self
        except Exception as e:
            logging.error(f"填写商品表单失败: {e}")
            self.take_screenshot("fill_product_form_failed")
            
            # 尝试使用JavaScript填写表单
            try:
                logging.info("尝试使用JavaScript填写商品表单")
                
                # 输入商品名称
                self.driver.execute_script(f"""
                var nameInput = document.querySelector('.el-dialog .el-form-item:nth-child(1) input');
                if (nameInput) {{
                    nameInput.value = "{name}";
                    nameInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                    console.log("已输入商品名称: {name}");
                }}
                """)
                
                # 选择商品分类 - 改进JavaScript选择分类的方法
                self.driver.execute_script(f"""
                // 点击分类下拉框
                var categorySelect = document.querySelector('.el-dialog .el-form-item:nth-child(2) .el-select input');
                if (categorySelect) {{
                    categorySelect.click();
                    console.log("已点击分类下拉框");
                    
                    // 等待下拉菜单显示
                    setTimeout(function() {{
                        // 查找可见的下拉菜单
                        var dropdowns = document.querySelectorAll('.el-select-dropdown:not([style*="display: none"])');
                        if (dropdowns.length > 0) {{
                            var dropdown = dropdowns[dropdowns.length-1];
                            var options = dropdown.querySelectorAll('.el-select-dropdown__item');
                            console.log("找到选项数量: " + options.length);
                            
                            var categoryFound = false;
                            for (var i = 0; i < options.length; i++) {{
                                if (options[i].textContent.includes('{category}')) {{
                                    options[i].click();
                                    console.log('已选择分类: ' + options[i].textContent);
                                    categoryFound = true;
                                    break;
                                }}
                            }}
                            
                            if (!categoryFound && options.length > 0) {{
                                options[0].click();
                                console.log('未找到匹配分类，已选择第一个选项: ' + options[0].textContent);
                            }}
                        }}
                    }}, 1000);
                }}
                """)
                time.sleep(2)  # 等待JavaScript执行完成
                
                # 输入商品价格
                self.driver.execute_script(f"""
                var priceInput = document.querySelector('.el-dialog .el-form-item:nth-child(3) input');
                if (priceInput) {{
                    priceInput.value = "{price}";
                    priceInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                    console.log("已输入商品价格: {price}");
                }}
                """)
                
                # 输入商品库存
                self.driver.execute_script(f"""
                var stockInput = document.querySelector('.el-dialog .el-form-item:nth-child(4) input');
                if (stockInput) {{
                    stockInput.value = "{stock}";
                    stockInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                    console.log("已输入商品库存: {stock}");
                }}
                """)
                
                # 选择商品状态
                self.driver.execute_script(f"""
                var statusLabel = Array.from(document.querySelectorAll('.el-dialog .el-radio')).find(el => el.textContent.includes('{status}'));
                if (statusLabel) {{
                    statusLabel.click();
                    console.log("已选择商品状态: {status}");
                }}
                """)
                
                # 输入商品描述
                if description:
                    self.driver.execute_script(f"""
                    var descriptionTextarea = document.querySelector('.el-dialog textarea');
                    if (descriptionTextarea) {{
                        descriptionTextarea.value = "{description}";
                        descriptionTextarea.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已输入商品描述: {description}");
                    }}
                    """)
                
                # 截图记录填写完表单的状态
                self.take_screenshot("product_form_filled_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript填写商品表单也失败: {e2}")
                self.take_screenshot("fill_product_form_js_failed")
                raise
    
    def submit_product_form(self):
        """
        提交商品表单
        """
        logging.info("提交商品表单")
        
        try:
            confirm_button = self.wait.until(EC.element_to_be_clickable(self.DIALOG_CONFIRM_BUTTON))
            confirm_button.click()
            logging.info("已点击确认按钮")
            
            # 等待对话框消失
            try:
                WebDriverWait(self.driver, 5).until(EC.invisibility_of_element_located(self.DIALOG))
                logging.info("对话框已关闭，表单提交成功")
            except TimeoutException:
                logging.warning("等待对话框消失超时，可能提交失败")
            
            # 等待可能的成功提示消息
            time.sleep(2)
            
            # 截图记录提交结果
            self.take_screenshot("product_form_submitted")
            
            return self
        except Exception as e:
            logging.error(f"提交商品表单失败: {e}")
            self.take_screenshot("submit_product_form_failed")
            
            # 尝试使用JavaScript点击确认按钮
            try:
                logging.info("尝试使用JavaScript提交商品表单")
                self.driver.execute_script("""
                var confirmButton = document.querySelector('.dialog-footer .el-button--primary');
                if (confirmButton) {
                    confirmButton.click();
                    console.log("已通过JavaScript点击确认按钮");
                } else {
                    console.error("未找到确认按钮");
                }
                """)
                
                # 等待对话框消失
                time.sleep(3)
                
                # 截图记录提交结果
                self.take_screenshot("product_form_submitted_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript提交商品表单也失败: {e2}")
                self.take_screenshot("submit_product_form_js_failed")
                raise
    
    def cancel_product_form(self):
        """
        取消商品表单
        """
        logging.info("取消商品表单")
        
        try:
            cancel_button = self.wait.until(EC.element_to_be_clickable(self.DIALOG_CANCEL_BUTTON))
            cancel_button.click()
            logging.info("已点击取消按钮")
            
            # 等待对话框消失
            WebDriverWait(self.driver, 5).until(EC.invisibility_of_element_located(self.DIALOG))
            logging.info("对话框已关闭，表单已取消")
            
            return self
        except Exception as e:
            logging.error(f"取消商品表单失败: {e}")
            self.take_screenshot("cancel_product_form_failed")
            raise
    
    def is_product_added_successfully(self, name):
        """
        检查商品是否添加成功
        
        Args:
            name: 商品名称
            
        Returns:
            bool: 是否找到添加的商品
        """
        logging.info(f"检查商品 '{name}' 是否添加成功")
        
        try:
            # 搜索新添加的商品
            self.search_product(name=name)
            
            # 检查搜索结果中是否包含该商品
            return self.is_product_in_results(name=name)
        except Exception as e:
            logging.error(f"检查商品是否添加成功失败: {e}")
            self.take_screenshot("check_product_added_failed")
            return False
    
    def click_first_row_edit_button(self):
        """
        点击表格第一行的编辑按钮
        """
        logging.info("点击表格第一行的编辑按钮")
        
        try:
            # 等待表格加载完成
            self.wait.until(EC.visibility_of_element_located(self.PRODUCT_TABLE))
            
            # 截图记录表格状态
            self.take_screenshot("before_edit_product")
            
            # 点击第一行的编辑按钮
            edit_button = self.wait.until(EC.element_to_be_clickable(self.FIRST_ROW_EDIT_BUTTON))
            edit_button.click()
            logging.info("已点击第一行的编辑按钮")
            
            # 等待编辑对话框出现
            self.wait.until(EC.visibility_of_element_located(self.DIALOG))
            
            # 验证对话框标题是否包含"编辑商品"
            dialog_title = self.wait.until(EC.visibility_of_element_located(self.DIALOG_TITLE))
            if "编辑商品" in dialog_title.text:
                logging.info("编辑商品对话框已打开")
            else:
                logging.warning(f"对话框标题不是'编辑商品'，实际标题是: {dialog_title.text}")
            
            # 截图记录对话框状态
            self.take_screenshot("edit_product_dialog_opened")
            
            return self
        except Exception as e:
            logging.error(f"点击第一行编辑按钮失败: {e}")
            self.take_screenshot("click_edit_button_failed")
            
            # 尝试使用JavaScript点击
            try:
                logging.info("尝试使用JavaScript点击第一行编辑按钮")
                self.driver.execute_script("""
                var editButton = document.querySelector('table tbody tr:first-child button.el-button--primary');
                if (editButton) {
                    editButton.click();
                    console.log('已通过JavaScript点击第一行编辑按钮');
                } else {
                    console.error('未找到第一行编辑按钮');
                }
                """)
                
                # 等待对话框出现
                time.sleep(2)
                self.take_screenshot("edit_product_dialog_opened_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript点击第一行编辑按钮也失败: {e2}")
                self.take_screenshot("click_edit_button_js_failed")
                raise
    
    def get_first_product_name(self):
        """
        获取表格第一行的商品名称
        
        Returns:
            str: 商品名称
        """
        try:
            # 等待表格加载完成
            self.wait.until(EC.visibility_of_element_located(self.PRODUCT_TABLE))
            
            # 获取第一行的商品名称
            first_row_name = self.driver.find_element(By.XPATH, "//table[contains(@class, 'el-table')]//tbody/tr[1]/td[3]").text
            logging.info(f"获取到第一行商品名称: {first_row_name}")
            return first_row_name
        except Exception as e:
            logging.error(f"获取第一行商品名称失败: {e}")
            self.take_screenshot("get_first_product_name_failed")
            
            # 尝试使用JavaScript获取
            try:
                logging.info("尝试使用JavaScript获取第一行商品名称")
                name = self.driver.execute_script("""
                var firstRow = document.querySelector('table tbody tr:first-child');
                if (firstRow) {
                    var nameCell = firstRow.querySelector('td:nth-child(3)');
                    return nameCell ? nameCell.textContent.trim() : '';
                }
                return '';
                """)
                logging.info(f"通过JavaScript获取到第一行商品名称: {name}")
                return name
            except Exception as e2:
                logging.error(f"使用JavaScript获取第一行商品名称也失败: {e2}")
                return ""
    
    def edit_product_form(self, name=None, category=None, price=None, stock=None, status=None, description=None):
        """
        编辑商品表单
        
        Args:
            name: 商品名称，可选
            category: 商品分类，可选
            price: 商品价格，可选
            stock: 商品库存，可选
            status: 商品状态，可选（上架/下架）
            description: 商品描述，可选
        """
        logging.info(f"编辑商品表单: 名称={name}, 分类={category}, 价格={price}, 库存={stock}, 状态={status}")
        
        try:
            # 确保对话框已显示
            self.wait.until(EC.visibility_of_element_located(self.DIALOG))
            
            # 修改商品名称
            if name is not None:
                name_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_PRODUCT_NAME_INPUT))
                name_input.clear()
                name_input.send_keys(name)
                logging.info(f"已修改商品名称为: {name}")
            
            # 修改商品分类
            if category is not None:
                # 点击分类下拉框
                category_select = self.wait.until(EC.element_to_be_clickable(self.DIALOG_CATEGORY_SELECT))
                category_select.click()
                logging.info("已点击分类下拉框")
                time.sleep(1)  # 等待下拉菜单显示
                
                # 截图记录下拉菜单状态
                self.take_screenshot("category_dropdown_opened")
                
                # 定位并点击下拉菜单中的选项
                try:
                    # 使用更精确的定位器找到可见的下拉菜单中的选项
                    dropdown_items = self.wait.until(EC.presence_of_all_elements_located(self.DROPDOWN_ITEM))
                    logging.info(f"找到 {len(dropdown_items)} 个下拉选项")
                    
                    # 遍历选项并查找匹配的分类
                    category_found = False
                    for item in dropdown_items:
                        if category in item.text:
                            logging.info(f"找到匹配的分类选项: {item.text}")
                            # 使用JavaScript点击，避免可能的元素遮挡问题
                            self.driver.execute_script("arguments[0].click();", item)
                            category_found = True
                            logging.info(f"已选择商品分类: {category}")
                            break
                    
                    if not category_found:
                        logging.warning(f"未找到匹配的分类: {category}")
                        # 尝试使用索引选择第一个选项
                        if dropdown_items:
                            self.driver.execute_script("arguments[0].click();", dropdown_items[0])
                            logging.info(f"已选择第一个可用分类: {dropdown_items[0].text}")
                except Exception as e:
                    logging.error(f"选择分类失败: {e}")
                    # 使用JavaScript尝试选择分类
                    self.driver.execute_script(f"""
                    var dropdowns = document.querySelectorAll('.el-select-dropdown:not([style*="display: none"])');
                    if (dropdowns.length > 0) {{
                        var items = dropdowns[dropdowns.length-1].querySelectorAll('.el-select-dropdown__item');
                        console.log("找到 " + items.length + " 个下拉选项");
                        
                        var categoryFound = false;
                        for (var i = 0; i < items.length; i++) {{
                            if (items[i].textContent.includes('{category}')) {{
                                items[i].click();
                                console.log('已选择分类: ' + items[i].textContent);
                                categoryFound = true;
                                break;
                            }}
                        }}
                        
                        if (!categoryFound && items.length > 0) {{
                            items[0].click();
                            console.log('未找到匹配分类，已选择第一个选项: ' + items[0].textContent);
                        }}
                    }}
                    """)
                
                time.sleep(1)  # 等待选择生效
                self.take_screenshot("after_category_selection")
            
            # 修改商品价格
            if price is not None:
                price_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_PRICE_INPUT))
                # 对于数字输入框，先清除再设置值
                self.driver.execute_script(f"arguments[0].value = ''; arguments[0].dispatchEvent(new Event('input'));", price_input)
                price_input.send_keys(str(price))
                logging.info(f"已修改商品价格为: {price}")
            
            # 修改商品库存
            if stock is not None:
                stock_input = self.wait.until(EC.visibility_of_element_located(self.DIALOG_STOCK_INPUT))
                # 对于数字输入框，先清除再设置值
                self.driver.execute_script(f"arguments[0].value = ''; arguments[0].dispatchEvent(new Event('input'));", stock_input)
                stock_input.send_keys(str(stock))
                logging.info(f"已修改商品库存为: {stock}")
            
            # 修改商品状态
            if status is not None:
                if status == "上架":
                    status_radio = self.wait.until(EC.element_to_be_clickable(self.DIALOG_STATUS_RADIO_UP))
                else:
                    status_radio = self.wait.until(EC.element_to_be_clickable(self.DIALOG_STATUS_RADIO_DOWN))
                status_radio.click()
                logging.info(f"已修改商品状态为: {status}")
            
            # 修改商品描述
            if description is not None:
                description_textarea = self.wait.until(EC.visibility_of_element_located(self.DIALOG_DESCRIPTION_TEXTAREA))
                description_textarea.clear()
                description_textarea.send_keys(description)
                logging.info(f"已修改商品描述为: {description}")
            
            # 截图记录填写完表单的状态
            self.take_screenshot("product_form_edited")
            
            return self
        except Exception as e:
            logging.error(f"编辑商品表单失败: {e}")
            self.take_screenshot("edit_product_form_failed")
            
            # 尝试使用JavaScript编辑表单
            try:
                logging.info("尝试使用JavaScript编辑商品表单")
                
                # 修改商品名称
                if name is not None:
                    self.driver.execute_script(f"""
                    var nameInput = document.querySelector('.el-dialog .el-form-item:nth-child(1) input');
                    if (nameInput) {{
                        nameInput.value = "{name}";
                        nameInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已修改商品名称为: {name}");
                    }}
                    """)
                
                # 修改商品分类
                if category is not None:
                    self.driver.execute_script(f"""
                    // 点击分类下拉框
                    var categorySelect = document.querySelector('.el-dialog .el-form-item:nth-child(2) .el-select input');
                    if (categorySelect) {{
                        categorySelect.click();
                        console.log("已点击分类下拉框");
                        
                        // 等待下拉菜单显示
                        setTimeout(function() {{
                            // 查找可见的下拉菜单
                            var dropdowns = document.querySelectorAll('.el-select-dropdown:not([style*="display: none"])');
                            if (dropdowns.length > 0) {{
                                var dropdown = dropdowns[dropdowns.length-1];
                                var options = dropdown.querySelectorAll('.el-select-dropdown__item');
                                console.log("找到选项数量: " + options.length);
                                
                                var categoryFound = false;
                                for (var i = 0; i < options.length; i++) {{
                                    if (options[i].textContent.includes('{category}')) {{
                                        options[i].click();
                                        console.log('已选择分类: ' + options[i].textContent);
                                        categoryFound = true;
                                        break;
                                    }}
                                }}
                                
                                if (!categoryFound && options.length > 0) {{
                                    options[0].click();
                                    console.log('未找到匹配分类，已选择第一个选项: ' + options[0].textContent);
                                }}
                            }}
                        }}, 1000);
                    }}
                    """)
                    time.sleep(2)  # 等待JavaScript执行完成
                
                # 修改商品价格
                if price is not None:
                    self.driver.execute_script(f"""
                    var priceInput = document.querySelector('.el-dialog .el-form-item:nth-child(3) input');
                    if (priceInput) {{
                        priceInput.value = "{price}";
                        priceInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已修改商品价格为: {price}");
                    }}
                    """)
                
                # 修改商品库存
                if stock is not None:
                    self.driver.execute_script(f"""
                    var stockInput = document.querySelector('.el-dialog .el-form-item:nth-child(4) input');
                    if (stockInput) {{
                        stockInput.value = "{stock}";
                        stockInput.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已修改商品库存为: {stock}");
                    }}
                    """)
                
                # 修改商品状态
                if status is not None:
                    self.driver.execute_script(f"""
                    var statusLabel = Array.from(document.querySelectorAll('.el-dialog .el-radio')).find(el => el.textContent.includes('{status}'));
                    if (statusLabel) {{
                        statusLabel.click();
                        console.log("已修改商品状态为: {status}");
                    }}
                    """)
                
                # 修改商品描述
                if description is not None:
                    self.driver.execute_script(f"""
                    var descriptionTextarea = document.querySelector('.el-dialog textarea');
                    if (descriptionTextarea) {{
                        descriptionTextarea.value = "{description}";
                        descriptionTextarea.dispatchEvent(new Event('input', {{ bubbles: true }}));
                        console.log("已修改商品描述为: {description}");
                    }}
                    """)
                
                # 截图记录填写完表单的状态
                self.take_screenshot("product_form_edited_js")
                
                return self
            except Exception as e2:
                logging.error(f"使用JavaScript编辑商品表单也失败: {e2}")
                self.take_screenshot("edit_product_form_js_failed")
                raise
    
    def is_product_edited_successfully(self, name):
        """
        检查商品是否编辑成功
        
        Args:
            name: 商品名称
            
        Returns:
            bool: 是否找到编辑后的商品
        """
        logging.info(f"检查商品 '{name}' 是否编辑成功")
        
        try:
            # 搜索编辑后的商品
            self.search_product(name=name)
            
            # 检查搜索结果中是否包含该商品
            return self.is_product_in_results(name=name)
        except Exception as e:
            logging.error(f"检查商品是否编辑成功失败: {e}")
            self.take_screenshot("check_product_edited_failed")
            return False 